const menu_Dao = require("@/dao/menu");
const z_base_Dao = require("@/dao/z_base");
const MenuModal = require("@/model/Menu");
const RDBCModal = require("@/model/RDBC");
const { ErrorCode } = require("@/utils/r/code");

const menu = {
  async GetUserMenuTree(userInfoId) {
    const menuList = await menu_Dao.GetMenusByUserInfoId(userInfoId);
    //过滤出一级菜单 parent_id = 0 的菜单
    const firstLevelMenuList = this.getFirstLevelMenus(menuList);

    // 获取存储子菜单的 map
    const menuChildrenMap = this.getMenuChildrenMap(menuList);

    // 将一级 Menu 列表转成 UserMenuVo 列表, 主要处理其 Children
    return this.menus2UserMenuVos(firstLevelMenuList, menuChildrenMap);
  },
  /**
   *  过滤一级菜单
   * @param {*} menuList
   */
  getFirstLevelMenus(menuList) {
    //找出一级菜单
    const firstLevelMenus = menuList.filter((item) => item.parent_id == 0);
    this.sortMenu(firstLevelMenus);
    return firstLevelMenus;
  },
  /**
   * 获取存储子菜单的 map
   */
  getMenuChildrenMap(menus) {
    //定义一个map结构
    let mcMap = {};
    for (const menu of menus) {
      if (menu.parent_id !== 0) {
        //将同一个父级的子菜单放在一起
        if (!mcMap[menu.parent_id]) {
          mcMap[menu.parent_id] = [];
        }
        mcMap[menu.parent_id].push(menu);
      }
    }
    return mcMap;
  },
  /**
   * 构建用户菜单的树形结构数据, []model.Menu => []resp.UserMenuVo
   * @param {*} firstLevelMenuList
   * @param {*} childrenMap
   */
  menus2UserMenuVos(firstLevelMenuList, childrenMap) {
    let resList = [];

    for (let firstLevelMenu of firstLevelMenuList) {
      let userMenu; //用户菜单
      let userMenuChildren = []; //用户菜单的子用户菜单

      const children = childrenMap[firstLevelMenu.id]; // 子菜单
      //过滤非子菜单项
      if (children && children.length > 0) {
        userMenu = this.menu2UserMenuVo(firstLevelMenu);
        this.sortMenu(children); //排序
        for (const child of children) {
          userMenuChildren.push(this.menu2UserMenuVo(child));
        }
      } else {
        //没有子菜单的项
        userMenu = {
          id: firstLevelMenu.id,
          path: firstLevelMenu.path,
          name: firstLevelMenu.name,
          component: firstLevelMenu.component,
          order_num: firstLevelMenu.order_num,
          hidden: firstLevelMenu.is_hidden === 1,
          keep_alive: firstLevelMenu.keep_alive === 1,
          redirect: firstLevelMenu.redirect,
        };
        const tmpUserMenu = this.menu2UserMenuVo(firstLevelMenu);
        userMenuChildren.push(tmpUserMenu);
      }
      //将子菜单作为children属性插入
      userMenu.children = userMenuChildren;
      resList.push(userMenu);
    }
    return resList;
  },
  menu2UserMenuVo(menu) {
    return {
      id: menu.id,
      name: menu.name,
      path: menu.path,
      component: menu.component,
      icon: menu.icon,
      order_num: menu.order_num,
      hidden: menu.is_hidden === 1,
      keep_alive: menu.keep_alive === 1,
      parent_id: menu.parent_id,
      redirect: menu.redirect,
    };
  },
  /**
   * 排序 以 orderNum 排序
   * @param {*} firstLevelMenus
   */
  sortMenu(firstLevelMenus) {
    firstLevelMenus.sort((a, b) => a.order_num - b.order_num);
  },
  async GetTreeList(query) {
    const menuList = await menu_Dao.GetMenus(query);
    //过滤出一级菜单 parent_id = 0 的菜单
    const firstLevelMenuList = this.getFirstLevelMenus(menuList);
    //获取存储子菜单的map
    const menuChildrenMap = this.getMenuChildrenMap(menuList);
    // 将一级 Menu 列表转成 MenuVo 列表, 主要处理其 Children
    let list = this.menus2MenuVos(firstLevelMenuList, menuChildrenMap);
    //方便前端展示处理
    list.forEach((item) => {
      if (item?.children?.length === 0) delete item.children;
    });
    return {
      pageData: list,
      total: list.length,
    };
  },
  menus2MenuVos(firstLevelMenuList, menuChildrenMap) {
    let resMenuVos = [];
    for (let i = 0; i < firstLevelMenuList.length; i++) {
      let firstLevelMenu = firstLevelMenuList[i];
      // 尝试将一级菜单转 MenuV, 还需要处理 Children
      let menuVo = this.menu2MenuVo(firstLevelMenu);
      //获取当前菜单的子菜单

      let menuChildren = menuChildrenMap[firstLevelMenu.id];
      let childMenuVos = [];

      if (menuChildren && menuChildren.length > 0) {
        this.sortMenu(menuChildren);
        // 对子菜单进行 []menu => []menuVo
        for (let childMenu of menuChildren) {
          childMenuVos.push(this.menu2MenuVo(childMenu));
        }
      }

      menuVo.children = childMenuVos;
      resMenuVos.push(menuVo);
      delete menuChildrenMap[firstLevelMenu.id]; //删除已经构建的菜单
    }
    if (Object.keys(menuChildrenMap).length > 0) {
      let menuChildren = [];
      for (let v of Object.values(menuChildrenMap)) {
        menuChildren.push(...v);
      }
      this.sortMenu(menuChildren);
      for (let menu of menuChildren) {
        resMenuVos.push(this.menu2MenuVo(menu));
      }
    }
    return resMenuVos;
  },
  menu2MenuVo(menu) {
    return {
      id: menu.id,
      name: menu.name,
      path: menu.path,
      component: menu.component,
      icon: menu.icon,
      created_at: menu.created_at,
      order_num: menu.order_num,
      is_hidden: menu.is_hidden === 1,
      parent_id: menu.parent_id,
      redirect: menu.redirect,
      keep_alive: menu.keep_alive === 1,
    };
  },
  async SaveOrUpdate(data, userInfoId) {
    let [[{ role_id }]] = await global.mysqlPool.execute(
      `select role_id from user_role where user_id = ${userInfoId}`
    );

    //更新的时候数据中包含id
    const existByName = await z_base_Dao.GetOne(MenuModal.Menu, {
      name: data.name,
    });

    if (existByName && existByName?.id !== data?.id) {
      return ErrorCode.ERROR_MENU_NAME_EXIST;
    }

    //前端将keepalive设置为true或者false了需要进行处理
    data.keep_alive = data.keep_alive ? 1 : 0;
    data.updated_at = new Date().toLocaleString();
    if (data.id) {
      // 更新
      await z_base_Dao.UpdatesMap(MenuModal.Menu, data, { id: data.id });
    } else {
      //创建
      data.created_at = new Date().toLocaleString();
      let { id } = await z_base_Dao.Create(MenuModal.Menu, data);
      // await global.mysqlPool.execute(
      //   `insert into role_menu (role_id,menu_id) values (${role_id},${id})`
      // );
    }
    return ErrorCode.OK;
  },
  async Delete(menuId) {
    //查询删除的菜单是否存在
    const existMenuById = await z_base_Dao.GetOne(MenuModal.Menu, {
      id: menuId,
    });
    if (!existMenuById) {
      return ErrorCode.ERROR_MENU_NOT_EXIST;
    }
    //检测对应的role_menu下是否存在数据
    const existRoleMenu = await z_base_Dao.GetOne(RDBCModal.RoleMenu, {
      menu_id: menuId,
    });
    if (existRoleMenu && existRoleMenu.menu_id !== 0) {
      //菜单被使用的时候不允许删除查到具体数据返回具有id
      return ErrorCode.ERROR_MENU_USED_BY_ROLE;
    }
    if (existMenuById && existMenuById.parent_id === 0) {
      //检查是否有子菜单,存在则不允许删除
      let count = await z_base_Dao.Count2(MenuModal.Menu, {
        parent_id: menuId,
      });
      if (count !== 0) {
        return ErrorCode.ERROR_MENU_HAS_CHILDREN;
      }
    }
    //删除菜单和相关的内容
    await z_base_Dao.Delete(MenuModal.Menu, { id: menuId });
    await z_base_Dao.Delete(RDBCModal.RoleMenu, { menu_id: menuId });
    return ErrorCode.OK;
  },
  // 获取菜单选项列表(树形)
  async GetOptionList() {
    let resList = [];
    let [menus] = await global.mysqlPool.execute(
      `select id,name,parent_id,order_num from menu`
    );
    let firstLevelMenus = this.getFirstLevelMenus(menus);
    let childrenMap = this.getMenuChildrenMap(menus);
    for (let item of firstLevelMenus) {
      let childrenOptionVos = [];
      //父级id去匹配子菜单
      let children = childrenMap[item.id];
      if (children && children.length > 0) {
        this.sortMenu(children);
        for (let menu of children) {
          childrenOptionVos.push({
            key: menu.id,
            title: menu.name,
            children: null,
          });
        }
      }
      resList.push({
        key: item.id,
        title: item.name,
        children: childrenOptionVos.length > 0 ? childrenOptionVos : null, //跟原项目数据返回保持统一
      });
    }
    return resList;
  },
};

module.exports = menu;
